package com.youdoneed.friends.recommanderFacePicture;

import com.querydsl.sql.SQLQuery;
import com.querydsl.sql.SQLQueryFactory;
import com.querydsl.sql.dml.SQLUpdateClause;
import com.youdoneed.base.application.AppException;
import com.youdoneed.base.common.GlobalIdWorker;
import com.youdoneed.base.pagination.Page;
import com.youdoneed.friends.application.QueryHelper;
import com.youdoneed.friends.common.util.StringUUIdUtil;
import com.youdoneed.friends.model.FaceNewsRelation;
import com.youdoneed.friends.model.RecommandFacePicture;
import com.youdoneed.friends.query.QFaceNewsRelation;
import com.youdoneed.friends.query.QRecommandFacePicture;
import com.youdoneed.friends.vo.IndexFacePictureVo;
import com.youdoneed.friends.vo.NewsVo;
import com.youdoneed.news.feign.NewsClient;
import com.youdoneed.news.model.CmfPostsListVo;
import com.youdoneed.user.feign.UserFeignClient;
import com.youdoneed.user.model.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created by lid on 2017/11/21 0021.
 */
@Service
@Transactional
public class RecommandFacePictureService {

    private static final String DIRECTIONUP = "up";

    private static final String DIRECTIONDOWN = "down";

    private static final String NEWSMAKER = "newsmaker";

    private static final String RECOMMANDFACE = "recommandface";

    private final Logger logger = LoggerFactory.getLogger(RecommandFacePictureService.class);

    @Autowired
    private SQLQueryFactory queryFactory;

    @Autowired
    private UserFeignClient userFeignClient;

    @Autowired
    private NewsClient newsClient;

    private QRecommandFacePicture qRecommandFacePicture = QRecommandFacePicture.RecommandFacePicture;

    private QFaceNewsRelation qFaceNewsRelation = QFaceNewsRelation.FaceNewsRelation;

    public Page<FaceNewsRelation> getNewsByPictureId(Paging paging, String facePictureId) {
        if (!StringUtils.hasText(facePictureId)) {
            throw new AppException("facePictureId为空!");
        }

        SQLQuery<FaceNewsRelation> query = queryFactory.selectFrom(qFaceNewsRelation)
                .where(qFaceNewsRelation.facePictureId.eq(facePictureId))
                .orderBy(qFaceNewsRelation.sort.asc());

        return QueryHelper.queryPage(paging, query);
    }

    public void deleteNewsByRelationId(String faceNewsRelationId) {
        if (!StringUtils.hasText(faceNewsRelationId)) {
            throw new AppException("faceNewsRelationId为空!");
        }

        queryFactory.delete(qFaceNewsRelation)
                .where(qFaceNewsRelation.faceNewsRelationId.eq(faceNewsRelationId))
                .execute();
    }

    public RecommandFacePicture getFacePictureById(String facePictureId) {
        if (!StringUtils.hasText(facePictureId)) {
            throw new AppException("facePictureId为空!");
        }

        return queryFactory.selectFrom(qRecommandFacePicture)
                .where(qRecommandFacePicture.facePictureId.eq(facePictureId))
                .fetchOne();
    }

    public FaceNewsRelation getFaceNewsRelationById(String faceNewsRelationId) {
        if (!StringUtils.hasText(faceNewsRelationId)) {
            throw new AppException("faceNewsRelationId为空!");
        }

        return queryFactory.selectFrom(qFaceNewsRelation)
                .where(qFaceNewsRelation.faceNewsRelationId.eq(faceNewsRelationId))
                .fetchOne();
    }

    public Page<RecommandFacePicture> getAllPicturesByPage(Paging paging, String type) {
        SQLQuery<RecommandFacePicture> query = queryFactory.selectFrom(qRecommandFacePicture)
                .where(qRecommandFacePicture.type.eq(type))
                .orderBy(qRecommandFacePicture.sort.asc());
        return QueryHelper.queryPage(paging, query);
    }

    public void addPicture(String pictureUrl, String mark, String type, Integer display) {
        if (!StringUtils.hasText(pictureUrl)) {
            throw new AppException("图片地址链接为空!");
        }

        if (!StringUtils.hasText(type)) {
            throw new AppException("图片类型为空!");
        }

        RecommandFacePicture picture = new RecommandFacePicture();
        picture.setCreateDate(new Date());
        picture.setFacePictureId(GlobalIdWorker.nextString());
        picture.setFacePictureUrl(pictureUrl);
        picture.setType(type);
        picture.setDisplay(display);
        if (StringUtils.hasText(mark)) {
            picture.setMark(mark);
        }
        Integer sort = queryFactory.select(qRecommandFacePicture.sort)
                .from(qRecommandFacePicture)
                .where(qRecommandFacePicture.type.eq(type))
                .orderBy(qRecommandFacePicture.sort.desc())
                .limit(1)
                .fetchOne();
        if (null == sort) {
            picture.setSort(1);
        } else {
            picture.setSort(sort + 1);
        }
        queryFactory.insert(qRecommandFacePicture).populate(picture).execute();
    }

    public void deletePicture(String facePictureId) {
        RecommandFacePicture recommandFacePicture = this.getFacePictureById(facePictureId);
        if (null == recommandFacePicture) {
            return;
        }
        queryFactory.delete(qFaceNewsRelation).where(qFaceNewsRelation.facePictureId.eq(facePictureId)).execute();
        queryFactory.delete(qRecommandFacePicture).where(qRecommandFacePicture.facePictureId.eq(facePictureId)).execute();
    }

    public void updatePicture(String facePictureId, String pictureUrl, String mark, Integer display) {
        if (!StringUtils.hasText(facePictureId)) {
            throw new AppException("facePictureId为空!");
        }

        if ((!StringUtils.hasText(pictureUrl))
                && (!StringUtils.hasText(mark))) {
            return;
        }

        RecommandFacePicture upDatePicture = new RecommandFacePicture();
        if (StringUtils.hasText(pictureUrl)) {
            upDatePicture.setFacePictureUrl(pictureUrl);
        }

        if (StringUtils.hasText(mark)) {
            upDatePicture.setMark(mark);
        }

        if (null != display) {
            upDatePicture.setDisplay(display);
        }

        SQLUpdateClause update = queryFactory.update(qRecommandFacePicture)
                .populate(upDatePicture)
                .where(qRecommandFacePicture.facePictureId.eq(facePictureId));

        update.execute();
    }

    /**
     * 置顶首页推荐人脸照
     * @param facePictureId
     */
    public void topPicture(String facePictureId){
        if (!StringUtils.hasText(facePictureId)) {
            throw new AppException("facePictureId为空!");
        }

        RecommandFacePicture recommandFacePicture = this.getFacePictureById(facePictureId);
        if(null == recommandFacePicture){
            return;
        }

        RecommandFacePicture lastOne = queryFactory.selectFrom(qRecommandFacePicture)
                .where(qRecommandFacePicture.sort.lt(recommandFacePicture.getSort()))
                .where(qRecommandFacePicture.type.eq(recommandFacePicture.getType()))
                .orderBy(qRecommandFacePicture.sort.asc())
                .fetchFirst();
        if(null == lastOne){
            return;
        }

        queryFactory.update(qRecommandFacePicture)
                .set(qRecommandFacePicture.sort, lastOne.getSort() - 1)
                .where(qRecommandFacePicture.facePictureId.eq(facePictureId))
                .execute();
    }

    /**
     * 置顶新闻人物的新闻
     * @param faceNewsRelationId
     */
    public void topRelationSort(String faceNewsRelationId){
        if (!StringUtils.hasText(faceNewsRelationId)) {
            throw new AppException("facePictureId为空!");
        }

        FaceNewsRelation faceNewsRelation = this.getFaceNewsRelationById(faceNewsRelationId);
        if(null == faceNewsRelation){
            return;
        }

        FaceNewsRelation lastOne = queryFactory.selectFrom(qFaceNewsRelation)
                .where(qFaceNewsRelation.sort.lt(faceNewsRelation.getSort()))
                .where(qFaceNewsRelation.facePictureId.eq(faceNewsRelation.getFacePictureId()))
                .orderBy(qFaceNewsRelation.sort.asc())
                .fetchFirst();
        if(null == lastOne){
            return;
        }

        queryFactory.update(qFaceNewsRelation)
                .set(qFaceNewsRelation.sort, lastOne.getSort() - 1)
                .where(qFaceNewsRelation.faceNewsRelationId.eq(faceNewsRelationId))
                .execute();
    }

    public void changeSort(String facePictureId, String direction) {
        if (!StringUtils.hasText(facePictureId)) {
            throw new AppException("facePictureId为空!");
        }

        if (!StringUtils.hasText(direction)) {
            throw new AppException("方向为空!");
        }

        RecommandFacePicture recommandFacePicture = this.getFacePictureById(facePictureId);

        if (RecommandFacePictureService.DIRECTIONUP.equals(direction)) {
            //向上
            RecommandFacePicture lastOne = queryFactory.selectFrom(qRecommandFacePicture)
                    .where(qRecommandFacePicture.sort.lt(recommandFacePicture.getSort()))
                    .where(qRecommandFacePicture.type.eq(recommandFacePicture.getType()))
                    .orderBy(qRecommandFacePicture.sort.desc())
                    .fetchFirst();

            if (null == lastOne) {
                throw new AppException("已经到顶了！");
            }

            this.swapSort(recommandFacePicture, lastOne);
        }

        if (RecommandFacePictureService.DIRECTIONDOWN.equals(direction)) {
            RecommandFacePicture lastOne = queryFactory.selectFrom(qRecommandFacePicture)
                    .where(qRecommandFacePicture.sort.gt(recommandFacePicture.getSort()))
                    .where(qRecommandFacePicture.type.eq(recommandFacePicture.getType()))
                    .orderBy(qRecommandFacePicture.sort.asc())
                    .fetchFirst();

            if (null == lastOne) {
                throw new AppException("已经到底了！");
            }
            this.swapSort(recommandFacePicture, lastOne);
        }
    }


    /**
     * 修改新闻的顺序
     *
     * @param facePictureId
     * @param direction
     */
    public void changeRelationSort(String faceNewsRelationId, String direction) {
        if (!StringUtils.hasText(faceNewsRelationId)) {
            throw new AppException("faceNewsRelationId为空!");
        }

        if (!StringUtils.hasText(direction)) {
            throw new AppException("方向为空!");
        }

        FaceNewsRelation faceNewsRelation = this.getFaceNewsRelationById(faceNewsRelationId);
        logger.info(faceNewsRelation.getNewsTitle());

        if (null == faceNewsRelation) {
            return;
        }

        if (RecommandFacePictureService.DIRECTIONUP.equals(direction)) {
            //向上
            FaceNewsRelation lastOne = queryFactory.selectFrom(qFaceNewsRelation)
                    .where(qFaceNewsRelation.facePictureId.eq(faceNewsRelation.getFacePictureId()))
                    .where(qFaceNewsRelation.sort.lt(faceNewsRelation.getSort()))
                    .orderBy(qFaceNewsRelation.sort.desc())
                    .fetchFirst();
            if (null == lastOne) {
                throw new AppException("已经到顶了！");
            }
            this.swapRelationSort(faceNewsRelation, lastOne);
        }

        if (RecommandFacePictureService.DIRECTIONDOWN.equals(direction)) {
            FaceNewsRelation lastOne = queryFactory.selectFrom(qFaceNewsRelation)
                    .where(qFaceNewsRelation.facePictureId.eq(faceNewsRelation.getFacePictureId()))
                    .where(qFaceNewsRelation.sort.gt(faceNewsRelation.getSort()))
                    .orderBy(qFaceNewsRelation.sort.asc())
                    .fetchFirst();

            if (null == lastOne) {
                throw new AppException("已经到底了！");
            }
            this.swapRelationSort(faceNewsRelation, lastOne);
        }
    }

    /**
     * 交换顺序。
     */
    public long swapRelationSort(FaceNewsRelation relationA, FaceNewsRelation relationB) {
        SQLUpdateClause update = queryFactory.update(qFaceNewsRelation);
        update.set(qFaceNewsRelation.sort, relationA.getSort())
                .where(qFaceNewsRelation.faceNewsRelationId.eq(relationB.getFaceNewsRelationId()))
                .addBatch();
        update.set(qFaceNewsRelation.sort, relationB.getSort())
                .where(qFaceNewsRelation.faceNewsRelationId.eq(relationA.getFaceNewsRelationId()))
                .addBatch();
        return update.execute();
    }


    /**
     * 交换顺序。
     */
    public long swapSort(RecommandFacePicture pictureA, RecommandFacePicture pictureB) {
        SQLUpdateClause update = queryFactory.update(qRecommandFacePicture);
        update.set(qRecommandFacePicture.sort, pictureA.getSort())
                .where(qRecommandFacePicture.facePictureId.eq(pictureB.getFacePictureId()))
                .addBatch();
        update.set(qRecommandFacePicture.sort, pictureB.getSort())
                .where(qRecommandFacePicture.facePictureId.eq(pictureA.getFacePictureId()))
                .addBatch();
        return update.execute();
    }

    /**
     * 获取首页顶部的照片
     *
     * @param userId
     * @return
     */
    public List<IndexFacePictureVo> getIndexFacePicture(String userId) {
        //获取新闻图片（最多2张）
        if (!StringUtils.hasText(userId)) {
            throw new AppException("userId为空");
        }

        List<RecommandFacePicture> listNewsPicture =
                queryFactory.selectFrom(qRecommandFacePicture)
                        .where(qRecommandFacePicture.type.eq(this.NEWSMAKER))
                        .where(qRecommandFacePicture.display.eq(1))
                        .orderBy(qRecommandFacePicture.sort.asc())
                        .fetch();
        logger.info("listNewsPicture.size()" + listNewsPicture.size());

        //获取可以加好友的推荐用户
        List<User> listUser = userFeignClient.getRecommandUsers().getData();
        List<IndexFacePictureVo> listIndexFacePictureVo = new ArrayList<>();

        if ((null != listNewsPicture)
                && (0 < listNewsPicture.size())) {
            for (RecommandFacePicture picture : listNewsPicture) {
                IndexFacePictureVo vo = new IndexFacePictureVo();
                vo.setPictureUrl(picture.getFacePictureUrl());
                vo.setType(this.NEWSMAKER);
                vo.setFacePictureId(picture.getFacePictureId());
                listIndexFacePictureVo.add(vo);
            }
        }

        if ((null != listUser)
                && (0 < listUser.size())) {
            for (User user : listUser) {
                IndexFacePictureVo vo = new IndexFacePictureVo();
                vo.setPictureUrl(user.getImageUrl());
                vo.setType(this.RECOMMANDFACE);
                listIndexFacePictureVo.add(vo);
            }
        }
        return listIndexFacePictureVo;
    }

    /**
     * 后台对新闻人物添加新闻关联
     *
     * @param facePictureId
     * @param listNewsVo
     */
    public void addNewsForPictureId(String facePictureId, List<NewsVo> listNewsVo) {
        if (!StringUtils.hasText(facePictureId)) {
            throw new AppException("facePictureId为空");
        }

        if ((null == listNewsVo)
                || (0 == listNewsVo.size())) {
            return;
        }

        Integer sort = queryFactory.select(qFaceNewsRelation.sort)
                .from(qFaceNewsRelation)
                .where(qFaceNewsRelation.facePictureId.eq(facePictureId))
                .orderBy(qFaceNewsRelation.sort.desc())
                .limit(1)
                .fetchOne();

        if (null == sort) {
            sort = 1;
        } else {
            sort = sort + 1;
        }

        for (NewsVo vo : listNewsVo) {
            FaceNewsRelation relation = new FaceNewsRelation();
            relation.setCreateDate(new Date());
            relation.setFaceNewsRelationId(StringUUIdUtil.getUUID());
            relation.setFacePictureId(facePictureId);
            relation.setNewsId(vo.getId());
            relation.setSort(sort);
            relation.setNewsTitle(vo.getPostTitle());
            sort++;
            queryFactory.insert(qFaceNewsRelation).populate(relation).execute();
        }
    }

    /**
     * 后台对新闻人物删除新闻关联
     *
     * @param listFaceNewsRelationIds
     */
    public void deleteNewsForPictureId(List<String> listFaceNewsRelationIds) {
        queryFactory.delete(qFaceNewsRelation)
                .where(qFaceNewsRelation.faceNewsRelationId.in(listFaceNewsRelationIds))
                .execute();
    }

    /**
     * 从关联表中根据图片id获取新闻id列表
     *
     * @param pictureId
     * @return
     */
    public List<Long> getNewsIdsByPictureId(String pictureId) {
        if (!StringUtils.hasText(pictureId)) {
            throw new AppException("pictureId为空");
        }

        return queryFactory.select(qFaceNewsRelation.newsId)
                .from(qFaceNewsRelation)
                .where(qFaceNewsRelation.facePictureId.eq(pictureId))
                .fetch();
    }

    /**
     * 通过图片id获取对应的新闻
     *
     * @return
     */
    public List<CmfPostsListVo> getPostsByPictureId(String pictureId) {
        if (!StringUtils.hasText(pictureId)) {
            throw new AppException("pictureId为空");
        }

        List<Long> listNewsId = this.getNewsIdsByPictureId(pictureId);
        if ((null == listNewsId)
                || (0 == listNewsId.size())) {
            return null;
        }

        logger.info("listNewsId.size():" + listNewsId.size());
        List<CmfPostsListVo> listNews = newsClient.getNewsByIds(listNewsId).getData();
        return listNews;
    }
}
